package ar.edu.caece.pl.asin.model.impl;

import ar.edu.caece.pl.alex.model.IToken;
import ar.edu.caece.pl.alex.model.impl.Token;
import ar.edu.caece.pl.asin.manager.IAnalizadorSintactico;
import ar.edu.caece.pl.asin.manager.impl.AbstractAnalizadorSintactico;
import ar.edu.caece.pl.asin.model.ITokenStream;

public class BloqueVarParam extends AbstractAnalizadorSintactico implements IAnalizadorSintactico {
	
	/* INICIALIZACION */	
	public BloqueVarParam ( ITokenStream ts ) {
		super(ts, false);
	}
	public BloqueVarParam ( ITokenStream ts, boolean debugMode ) {
		super(ts,debugMode);
	}

	
	/** 
	 * Devuelve true si reconoce los parametros de llamada a un procedimiento o funcion
	 */
	public boolean reconocer () {
		
		boolean recognized = true; //(asumimos correctitud hasta demostrar lo contrario)
		
		//----------------------------------------------
		//Agrego info de debug de la produccion
		em.debug( "Reconocer BloqueVarParam:");
		//----------------------------------------------
		
		/* <BLOQUE_VAR_PARAM> -> BYREF IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1> |
                      			 BYVAL IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1> |
                      			 IDENTIFICADOR       : <TIPO> <BLOQUE_VAR_PARAM_1> */
		
		//Primero reconozco Byref, Byval o si viene por default y agrego info de debug 
		if ( this.getTokenSiguiente().equals( new Token(IToken.PALABRA_RESERVADA_BYREF) ) ) {
			
			// <BLOQUE_VAR_PARAM> -> BYREF IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<BLOQUE_VAR_PARAM> -> BYREF IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>", this.getTokenSiguiente() );
			//----------------------------------------------
			
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_BYREF) ) {
				//El reconocerToken() habria adelantado el tokenStream hasta salir de esta iteracion del BloqueVarParam,
				//entonces no hay que seguir buscando sino salir
				return false;
			}
			
		} else if ( this.getTokenSiguiente().equals( new Token(IToken.PALABRA_RESERVADA_BYVAL) ) ) {
			
			// <BLOQUE_VAR_PARAM> -> BYVAL IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<BLOQUE_VAR_PARAM> -> BYVAL IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>", this.getTokenSiguiente() );
			//----------------------------------------------
			
			if ( !this.reconocerToken(IToken.PALABRA_RESERVADA_BYVAL) ) {
				return false;
			}
			
		} else if ( this.getTokenSiguiente().equals( new Token(IToken.TYPE_IDENTIFICADOR) ) ) {
			
			// <BLOQUE_VAR_PARAM> -> IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>
			
			//----------------------------------------------
			//Agrego info de debug de la produccion
			em.debug( "<BLOQUE_VAR_PARAM> -> IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>", this.getTokenSiguiente() );
			//----------------------------------------------
			
		} else {
			
			//No deberia darse el caso, pero si se llama a reconocer() en un estado incorrecto deberia salir por aqui
			em.error("Se esperaba " + IToken.PALABRA_RESERVADA_BYREF +
					 " o " + IToken.PALABRA_RESERVADA_BYVAL +
					 " o " + this.dic.getTokenDescription(IToken.TYPE_IDENTIFICADOR),
					this.getTokenSiguiente());
			
			//Tratamiento de errores
			em.recover(this.getClass(), this.tokenStream);
			
			return false;
		}
		
		//Luego el resto comun a las tres producciones IDENTIFICADOR : <TIPO> <BLOQUE_VAR_PARAM_1>
		
		if ( !this.reconocerToken(IToken.TYPE_IDENTIFICADOR) ) {
			return false;
		}
		
		if ( !this.reconocerToken(IToken.TYPE_DOS_PUNTOS) ) {
			return false;
		}

		IAnalizadorSintactico tipo = new Tipo(this.tokenStream, this.debugMode);
		recognized &= tipo.reconocer();
		
		// reconocer <BLOQUE_VAR_PARAM_1>
		if ( BloqueVarParam1.primeros(this.getTokenSiguiente()) ) {

			IAnalizadorSintactico bloqueVarParam1 = new BloqueVarParam1(this.tokenStream, this.debugMode);
			recognized &= bloqueVarParam1.reconocer();
		}
		
		return recognized;
	}
	
	public static boolean primeros(IToken token) {
		return  token.equals( new Token(IToken.PALABRA_RESERVADA_BYREF) ) ||
				token.equals( new Token(IToken.PALABRA_RESERVADA_BYVAL) ) ||
				token.equals( new Token(IToken.TYPE_IDENTIFICADOR) );
	}
}
